﻿using System;
using System.Runtime.InteropServices;

namespace SilverlightViewport.Common.Interop
{
    public class SilverlightViewer : AlmostUnknown
    {
        private delegate void SuppressBrowserEventsDelegate(IntPtr pStruct, int bSuppress);
        private delegate int CreateRenderTargetBitmapDelegate(IntPtr pStruct, int uBackground, int nOffsetX, int nOffsetY, int nWidth, int nHeight, IntPtr pvBits, out IntPtr pplRenderTargetBitmap);
        private delegate int ProcessInputDelegate(IntPtr pStruct, int msg, int wParam, int lParam, ref IntPtr curEvent, int x, int y, out IntPtr fHandled);

        private SuppressBrowserEventsDelegate m_suppressBrowserEvents;
        private CreateRenderTargetBitmapDelegate m_createRenderTargetBitmap;
        private ProcessInputDelegate m_processInput;

        public SilverlightViewer(IntPtr pStruct) : base(pStruct)
        {
            SetupSilverlightViewerMethods();
        }

        private void SetupSilverlightViewerMethods()
        {
            /* Read the COM v-table pointer */
            IntPtr pVtable = Marshal.ReadIntPtr(StructPointer);

            const int SUPPRESS_BROWSER_EVENTS_VTABLE_INDEX = 2;
            const int CREATE_RENDER_TARGET_BITMAP = 3;
            const int PROCESS_INPUT_DELEGATE = 4;

            /* Get the function pointer */
            IntPtr pFunc = Marshal.ReadIntPtr(pVtable, SUPPRESS_BROWSER_EVENTS_VTABLE_INDEX * IntPtr.Size);

            /* Cast the function pointer to a .NET delegate */
            m_suppressBrowserEvents = (SuppressBrowserEventsDelegate)Marshal.GetDelegateForFunctionPointer(pFunc, typeof(SuppressBrowserEventsDelegate));

            /* Rinse and repeat */
            pFunc = Marshal.ReadIntPtr(pVtable, CREATE_RENDER_TARGET_BITMAP * IntPtr.Size);
            m_createRenderTargetBitmap = (CreateRenderTargetBitmapDelegate)Marshal.GetDelegateForFunctionPointer(pFunc, typeof(CreateRenderTargetBitmapDelegate));

            /* Rinse and repeat */
            pFunc = Marshal.ReadIntPtr(pVtable, PROCESS_INPUT_DELEGATE * IntPtr.Size);
            m_processInput = (ProcessInputDelegate)Marshal.GetDelegateForFunctionPointer(pFunc, typeof(ProcessInputDelegate));
        }

        public void SuppressBrowserEvents(int bSuppress)
        {
            m_suppressBrowserEvents(StructPointer, bSuppress);
        }

        public int CreateRenderTargetBitmap(int uBackground, int nOffsetX, int nOffsetY, int nWidth, int nHeight, IntPtr pvBits, out IntPtr pplRenderTargetBitmap)
        {
            int hr = m_createRenderTargetBitmap(StructPointer, uBackground, nOffsetX, nOffsetY, nWidth, nHeight, pvBits, out pplRenderTargetBitmap);

            return hr;
        }

        public void ProcessInput(int msg, int wParam, int lParam, ref IntPtr curEvent, int x, int y, out IntPtr fHandled)
        {
            m_processInput(StructPointer, msg, wParam, lParam, ref curEvent, x, y, out fHandled);
        }
    }
}
